perm filename OBJCR.1[CLS,LSP] blob sn#847179 filedate 1987-10-15 generic text, type C, neo UTF8
COMMENT āŠ—   VALID 00011 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00003 00002	-foo- means the word foo in italics.  FOO means the word foo in boldface.
C00004 00003	Page 1-5   Creating Instances of Classes
C00006 00004	Page 1-27:  New Chapter:  Object Creation and Initialization 
C00013 00005	\beginsubSection{Terminology Related to Object Creation and Initialization}
C00017 00006	\beginsubSection{Declaring the Validity of Initargs}
C00020 00007	\beginsubsection{Defaulting of Initargs}
C00025 00008	\beginsubSection{Rules for Duplication of Initargs}
C00029 00009	\beginsubSection{Methods for {\bf INITIALIZE-INSTANCE }}
C00034 00010	\beginsubSection{Procedural Definition of {\bf MAKE-INSTANCE}}
C00038 00011	>>>> Mechanical Tasks:
C00052 ENDMK
CāŠ—;
-foo- means the word foo in italics.  FOO means the word foo in boldface.


>>>> New Writing 

Page 1-5   Creating Instances of Classes

[Replace existing text with this.   The goal is to give an overview of
creating instances.   It's too early to discuss initialization in detail
because we haven't discussed methods yet.]

The generic function {\bf make-instance} creates and returns a new
instance of a class.  The \OS\ provides a flexible means for specifying
how a new instance is to be initialized.  For example, it is possible to
specify the initial values for slots in newly-created instances, either by
giving an argument to {\bf make-instance} or by providing a default
initial value.  Further initialization activities can be performed by
methods written for generic functions that are part of the initialization
protocol.  The complete initialization protocol is described in the
section ``Object Creation and Initialization.''

Page 1-27:  New Chapter:  Object Creation and Initialization 

\beginSection{Object Creation and Initialization}

The generic function {\bf make-instance} creates and returns a new
instance of a class.  The first argument is a class or the name of a
class, and the remaining arguments are an {\bit initialization argument}
({\bit initarg}) list.  

Initialization consists of several distinct steps, including:  combining
the explicitly supplied initargs with default values for the
unsupplied initargs, checking the validity of the initargs, allocating
storage for the instance, filling slots with values, and executing
user-supplied methods which perform additional initialization.  The \OS\
defines {\bf make-instance} in a procedural way: each step is represented by
a generic function.  This provides a mechanism for to customizing each
step.  In addition, {\bf make-instance} is a generic function
and can be customized.

The \OS\ specifies default methods for each step, so there is well-defined
standard behavior for the entire initialization procedure.  The standard
behavior provides four simple mechanisms for controlling
initialization:

\beginlist

\item{\bull} Declaring a symbol to be an initarg for a slot, by 
   by using the {\bf :initarg} slot option. This allows one to
   provide a value for a slot in a call to {\bf make-instance}.  

\item{\bull} Supplying a default value form for an initarg, by using the
   {\bf :default-initargs} class option.   This default value is used if the
   initarg is not explicitly provided as an argument to {\bf make-instance}.

\item{\bull} Supplying a default value form for a slot, by using the {\bf
:initform} slot option.  This default value is stored in the slot if no
initarg associated with that slot is given as an argument to {\bf make-instance}
or defaulted by {\bf :default-initargs}.

\item{\bull} Defining methods for {\bf initialize-instance}.  The
slot-filling behavior described above is implemented by a system-supplied
default method for {\bf initialize-instance}.  Additional control over
initialization can be obtained by writing methods for {\bf
initialize-instance}.  In most cases {\bf :after} methods are appropriate
for this purpose, because they are called after the default method that
fills the slots and thus do not override the normal slot-filling behavior.

\endlist

Note that the object creation and initialization procedure can be
controlled at two different levels.   The standard behavior offers the 
four mechanisms mentioned above; this level can be considered the
Programmer Interface level.   At the meta-object level, greater control 
can be exerted
over each step of this procedure; this level can be
considered the interface for experimentation with alternative
object-oriented paradigms.

Note that the object creation and initialization procedure can be
controlled at two different levels.  The standard behavior offers the four
mechanisms mentioned above; this level can be considered the Programmer
Interface level.  At the Meta-object level, greater control can be exerted
over each step of this procedure; this level can be considered the
interface for experimentation with alternative
object-oriented paradigms.

There is one general guideline that helps distinguish between the Programmer
Interface and the Meta-object levels of programming.  To customize
behavior at the Programmer Interface level, methods 
that specialize on instances are written.  That is, the arguments that select
methods are instances.   To customize behavior at the Meta-object level,
methods that specialize on classes are written.  That is, the
arguments that select methods are classes.

\beginsubSection{Terminology Related to Object Creation and Initialization}

The terminology related to object creation and initialization is
presented here:

\beginlist

\item{\bull} {\bit Initarg}: An initarg (initialization argument) is a keyword
argument that can be used to control object creation and initialization.
The {\bf \&key} arguments to {\bf make-instance} are initargs.  It is
often convenient to use keyword symbols to name initargs, but the name of
an initarg can be any symbol, including {\bf nil}.  There are two
purposes for an initarg:  to fill a slot with a value or to provide an
argument for an initialization method.  A single initarg can be used for
more than one purpose.

\item{\bull} {\bit Initarg list}: An initarg list (initialization argument list)
is a list of alternating initarg names and values.  Its structure is
identical to a property list and also identical to the portion of an
argument list processed for {\bf \&key} parameters.  As in those lists, if
an initarg name appears more than once in an initarg list, the leftmost
occurrence supplies the value and the remaining occurrences are ignored.
The arguments to {\bf make-instance} (after the first argument) are an
initarg list.  As in an {\bf \&key} argument list, {\bf :allow-other-keys}
can appear in an initarg list, and if its value is non-{\bf nil},
error-checking of initarg names is disabled.

\item{\bull} {\bit Slot-filling initarg}: A slot-filling initarg is an initarg
associated with a slot.  If the initarg has a value in the initarg list,
the value is stored into the slot of the newly-created object, overriding
any initform associated with the slot.  A single initarg can fill more
than one slot.  A slot-filling initarg that fills a shared slot stores its
value into the shared slot, replacing any previous value.

\item{\bull} {\bit Method-implemented initarg}: A method-implemented
initarg is an initarg associated with a method.  A method-implemented
initarg is intended as an argument for one or more methods for {\bf
initialize-instance} or {\bf allocate-instance}.  When an object is
created, the method is called with the initarg's name and value as a named
argument and the method uses the value however it chooses.  If the initarg
has no value in the initarg list, the method's lambda-list supplies a
default value.

\endlist

\endsubSection%{Terminology Related to Object Creation and Initialization}
\beginsubSection{Declaring the Validity of Initargs}

The generic function {\bf make-instance} checks the validity of the
initargs and signals an error if an initarg is supplied that is not valid.
An initarg is declared as valid in the same place where its purpose
(whether slot-filling or method-implemented) is stated.

Slot-filling initargs are declared as valid by the {\bf :initarg} slot option
to {\bf defclass}.  The 
{\bf :initarg} slot option is inherited from superclasses.
Thus, the set of valid slot-filling initargs for a class is the union of
the initargs declared by the class and its superclasses.

Method-implemented initargs are declared as valid by defining methods for
{\bf initialize-instance} or {\bf allocate-instance}.  The keyword name of
each keyword parameter specifier in the method's lambda-list becomes a
method-implemented initarg for all classes for which this method is
applicable.  Thus, method inheritance controls the set of valid
method-implemented initargs.  

The set of valid initargs for a class is the union of the valid
slot-filling initargs, the valid method-implemented initargs, and the
pre-defined initarg {\bf :allow-other-keys}.  The default for {\bf
:allow-other-keys} is {\bf nil}, and its specification is the same as
Common Lisp defines for {\bf \&key} argument lists.

\endsubSection%{Declaring the Validity of Initargs}
\beginsubsection{Defaulting of Initargs}

A {\bit default value form} can be supplied for an initarg.  The way to
provide a default value form for either a slot-filling and
method-implemented initarg is to use the {\bf :default-initargs} class option.
A default value form is usually specified by a different class from the
class that declared the initarg as valid.  Thus, 
{\bf :default-initargs} is
usually used to supply a default value for an inherited initarg.

The {\bf :default-initargs} class option is inherited.   See ``Inheritance of 
Class Options.''

The {\bf :default-initargs} class option is a list of alternating initarg
names and forms.  Each form is the default value form for the
corresponding initarg.  The default value form of an initarg is used only
if that initarg does not appear in the arguments to {\bf make-instance}.
In that case, the default value form is evaluated in the lexical
environment of the {\bf defclass} form that supplied it, and the resulting
value is used as the initarg's value.  The initarg name and value are
appended to the initarg list supplied to {\bf make-instance}.  The result
is a {\bit defaulted initarg list} in which the explicitly supplied
initargs appear earlier in the list than the defaulted initargs.
Defaulted initargs are ordered according to the order in the class
precedence list of the classes that supplied the default values.

The {\bf :default-initargs} option is used only to provide default values for 
initargs; it does not declare a symbol as a valid initarg name.

There is a distinction between the purposes of {\bf :default-initargs} and
{\bf :initform}, with respect to slot-filling initargs.  The {\bf
:default-initargs} class option allows the user to give a default value
form for an initarg without knowing whether or not the initarg fills a
slot.  If that initarg is not explicitly supplied in a call to {\bf
make-instance}, the default value form is used, just as if it had been
supplied in the call.  In contrast, the {\bf :initform} slot option allows
the user to give a default initial value form for a slot.  An {\bf
:initform} is used only if no initarg associated with that slot is given
as an argument to {\bf make-instance} or defaulted by {\bf
:default-initargs}.  The two kinds of defaulting exist at different levels
of abstraction.

The \OS\ does not guarantee any given order of evaluation of
default-initarg forms and initforms.  If the order of evaluation is
important, {\bf initialize-instance} methods should be used instead.  In
most programs, the initforms and default-initarg forms are either
constants or simple forms that construct new objects; forms with
side-effects are permitted, but are not recommended.

\endsubsection%{Defaulting of Initargs}
\beginsubSection{Rules for Duplication of Initargs}
 
The following rules specify what happens when initargs are duplicated.

\beginlist

\item{\bull} The {\bf :initarg} slot option may be specified more than
once for a given slot.

\item{\bull} A single initarg can initialize more than one slot if the
same initarg name appears in more than one {\bf :initarg} slot option.

\item{\bull} It is valid for a given initarg name to be defined more than
once as a slot-filling initarg, as a method-implemented initarg, or both.

\item{\bull} If two initargs that initialize the same slot are given in
the arguments to {\bf make-instance}, the leftmost of these initargs in
the initarg list prevails, even if the two initargs have different names.
This behavior is consistent with the behavior of property lists and with the
portion of an argument list processed for {\bf \&key} parameters.

\item{\bull} If two different initargs that initialize the same slot have
default values, and neither is given explicitly in the arguments to
{\bf make-instance}, the initarg that appears in a 
{\bf :default-initargs} slot option
in the most specific class prevails, or if they appeared in the same
class, the one whose mention in :DEFAULT-INITARGS is leftmost in the
DEFCLASS form prevails.  During the defaulting of initargs, the defaults
are appended to the end of the initarg list in this order.

\item{\bull} If there are two different initargs that initialize the same
slot, and one was given explicitly in the arguments to {\bf make-instance} while
the other was defaulted using {\bf :default-initargs}, the explicit one prevails.
This follows from the previous two rules.

\item{\bull} If a slot has both an {bf :initform} and an {\bf :initarg}
slot option, and the slot-filling initarg is defaulted using {\bf
:default-initargs}, the initform is not used and is not evaluated.

\endlist


The following is an example of the above rules:

\screen!

  (defclass a () ((x :initarg a)))
  (defclass b (a) ((x :initarg b))
    (:default-initargs a 1 b 2))

                                 DEFAULTED 
  FORM                          INITARG LIST    CONTENTS OF X SLOT
  (make-instance 'b)            (a 1 b 2)               1
  (make-instance 'b 'a 3)       (a 3 b 2)               3
  (make-instance 'b 'b 4)       (b 4 a 1)               4
  (make-instance 'b 'a 1 'a 2)  (a 1 a 2 b 2)           1

\endscreen!

\endsubSection%{Rules for Duplication of Initargs}
\beginsubSection{Methods for {\bf INITIALIZE-INSTANCE }}

The generic function {\bf initialize-instance} uses standard method
combination.  Methods for {\bf initialize-instance} can be defined in
order to perform any initialization that cannot be achieved with the
simple slot-filling mechanisms.

During initialization, {\bf initialize-instance} is invoked
after the following actions have been taken:

\beginlist 

\item{\bull} The defaulted initarg list is computed by combining the
supplied initarg list with any default initargs for the class.

\item{\bull} The validity of the defaulted initarg list is checked.  If
any of the initargs has not been declared as valid, an error is signaled.

\item{\bull} A blank instance is created.

\endlist

The generic function {\bf initialize-instance} is then called with the
blank instance and the defaulted initarg list.  The system-supplied
default method is a primary method that initializes the slots with values
according to the initarg list. 
This default method behaves as follows on each slot, whether shared or
local:

\beginlist

\item{\bull} If an initarg in the defaulted initarg list fills that slot,
its value is stored into the slot.  (This is true even if a 
{\bf :before} method
has modified the slot.)

\item{\bull} Otherwise, if the slot has an initform, the initform is
evaluated and the result is stored into the slot.

\item{\bull} The duplicate-resolution rules mentioned in the section
``Rules for Duplication of Initargs'' are obeyed.

\endlist

User-defined {\bf :after} methods are a good way to customize 
this step of the initialization process because they will be run
after the default activities of {\bf initialize-instance}.
Care should be taken to not supply primary methods
that override the default primary method unless the default activities
of {\bf initialize-instance} are not desired.

The \OS\ provides two functions that are useful in the bodies of {\bf
initialize-instance} methods.  The function {\bf slot-boundp} returns a
boolean value that states whether the slot has a value; this enables
writing {\bf :after} methods for {\bf initialize-instance} that initialize
slots only if they have not already been initialized.  The function {\bf
slot-makunbound} restores a slot to the uninitialized state.

Implementations are permitted to make certain optimizations of {\bf
initialize-instance}.  The description of {\bf initialize-instance} in
Chapter~2 mentions the possible optimizations.  One possible optimization
has the following impact on user-supplied methods:  {\bf :before} and {\bf
:around} methods for {\bf initialize-instance} cannot rely on all the
slots being uninitialized.

\endsubSection%{Methods for INITIALIZE-INSTANCE }
\beginsubSection{Procedural Definition of {\bf MAKE-INSTANCE}}

The generic function
{\bf make-instance} behaves as if it were defined as follows, except that
certain optimizations are permitted: 

\screen!

(defmethod make-instance ((class standard-class) &rest initargs)
  (setq initargs (default-initargs class initargs))
  (check-initargs class initargs)  
  (let ((instance (apply #'allocate-instance class initargs)))
    (apply #'initialize-instance instance initargs)
    instance))

(defmethod make-instance ((class-name symbol) &rest initargs)
  (apply #'make-instance (symbol-class class-name) initargs))

\endscreen!

This procedure can be customized at either the Programmer Interface level,
the Meta-object level, or both.  

Customizing at the Programmer Interface level includes using the {\bf
:initform}, {\bf :initarg}, and {\bf :default-initargs} options to {\bf
defclass}, as well as defining methods for {\bf initialize-instance}.  The
Meta-object level supports extra customization by defining methods for:
{\bf default-initargs}, {\bf check-initargs}, and {\bf allocate-instance}.
Chapter~3 documents each of these generic functions and the
system-supplied default methods.

As noted above, certain optimizations of the {\bf make-instance} procedure are
permitted.  The description of {\bf initialize-instance} in Chapter~2 mentions
some possible optimizations to this procedure.   Additional
optimizations are possible, including inlining and constant-folding of
method lookup and method bodies, provided that the programming
environment either prohibits redefining these methods or updates
everything when they are redefined.  

Because of optimization, methods for the meta-object generic functions
listed may not actually be called on every call to {\bf make-instance} or may
not receive exactly the arguments that would be expected.  For example,
{\bf check-initargs} might actually be called before {\bf default-initargs} rather
than after, if it has already been determined that the default initargs
will pass {\bf check-initargs}.

\endsubSection%{Procedural Definition of {\bf MAKE-INSTANCE}}
>>>> Mechanical Tasks:

Page 1-8:  inheritance of :initarg  

The :INITARG slot-option is inherited from superclasses.  The set of
initargs that initialize a given slot is the union of the sets of initargs declared
in :INITARG slot-options with the same slot name in the class and its
superclasses.  

Page-9:  inheritance of :default-initargs (the only class option that is
inherited)

The :DEFAULT-INITARGS class option is inherited; the set of initargs for 
a class that are defaulted is the union of the sets of initargs 
specified in :DEFAULT-INITARGS class options of the class and its
superclasses.  When more than one default value form is supplied for a
given initarg, the default value form supplied by the class that appears
earliest in the class precedence list is used.

Page 1-21:   Congruent Lambda-lists for All Methods of a Generic Function

Replace the old rules with the new ones.   

Probably should add a note about on 1-21 about this:

The proposal assumes CL-Cleanup issue KEYWORD-ARGUMENT-NAME-PACKAGE:ANY, which
stated that the names of &key arguments do not have to be keyword symbols.
The terminology of CLtL is used for discussing keyword arguments, but it
should be understood that keyword names are not necessarily symbols in
the keyword package; that's just a default convention.

Page 2-15 (and onward)  DEFCLASS section

Add :INITARG and :DEFAULT-INITARGS to the syntax diagram.

Add this info: 

The :INITARG -name- slot-option -declares- an initarg named -name- and
-specifies- that this initarg initializes the slot to which the
slot-option is attached.  -name- is any symbol.  If the initarg has a
value, the value is stored into the slot and the slot's :INITFORM, if
any, is -not- evaluated.  If no initarg specified to initialize a given
slot has a value, then the slot is initialized according to the
:INITFORM (if any).  This slot option can appear any number of times.

The :DEFAULT-INITARGS option is followed by a list of alternating
initarg names and default-initarg forms.  If one of these initargs does
not appear in the initarg list supplied to MAKE-INSTANCE, the
corresponding default-initarg form is evaluated, then the initarg name
and the form's value are added to the end of the initarg list.  The form
is evaluated every time it is used.  The lexical environment in which
this form is evaluated is the lexical environment in which DEFCLASS was
evaluated.  The dynamic environment is the dynamic environment in which
MAKE-INSTANCE was called.  The :DEFAULT-INITARGS option may be specified
more than once.  However, an error is signaled if an initarg name
appears more than once in a single :DEFAULT-INITARGS option, or in more
than one :DEFAULT-INITARGS option for a single class.

>>>> Add descriptions of each of these functions to Chapter 2: 

(MAKE-INSTANCE -class- &key -initargs-...) => -instance-

Users call this function to create objects.  Class can be either a class or
the name of a class.  Meta-users can define new methods for MAKE-INSTANCE
to replace the object-creation protocol.  For details, see
the section "Object Creation and Initialization".

(INITIALIZE-INSTANCE instance &key &allow-other-keys)

MAKE-INSTANCE calls this with the freshly-created instance, any initargs that
were supplied to MAKE-INSTANCE, and any defaulted initargs.  Users define
methods for this to create method-implemented initargs.  Typically,
user-defined methods are :AFTER methods, however that is not a requirement.

The primary method for INITIALIZE-INSTANCE is system-supplied and takes care
of the slot-filling initargs.  For each slot (whether local or shared):

  - if an initarg was specified or defaulted that fills that slot, its
    value is stored into the slot.  (This is true even if a :BEFORE method
    has modified the slot.)

  - otherwise, if the slot is uninitialized and it has an initform, the
    initform is evaluated and the result is stored into the slot.

  - the duplicate-resolution rules mentioned in the section "Rules for
    Duplication of Initargs" are obeyed.

Implementations are permitted to optimize initforms that neither
produce nor depend on side-effects, by evaluating them and storing them
into slots before running any INITIALIZE-INSTANCE methods, rather than
handling them in the primary INITIALIZE-INSTANCE method.  (This might be
implemented by having the ALLOCATE-INSTANCE method copy a prototype
instance.)  

Implementations are permitted to optimize default value forms for 
slot-filling initargs by not actually consing the complete initarg list,
when the only method that would see the complete list is the 
system-supplied primary method, e.g. when no other methods use &REST.
In this case default value forms can be treated like initforms.  This
has no visible effects other than a performance improvement.

(SLOT-BOUNDP instance slot-name) => boolean

Allows writing INITIALIZE-INSTANCE :AFTER methods that only initialize slots if
they haven't been initialized already.

(SLOT-MAKUNBOUND instance slot-name) => instance

Restores a slot to the uninitialized condition.


>>>> Add descriptions of each of these functions to Chapter 3

>>> Functions underlying the tools

It is undefined what happens if you modify the values returned by any
of the functions in this section.  It is permitted, but not required,
for an implementation to return values that share with internal data
structures.  Some of these functions will be SETF'able; which ones
remain to be determined.

(CLASS-ALL-INITARGS class) => list of initarg names, including inherited
ones.  This is (REDUCE #'UNION (MAPCAR #'CLASS-DIRECT-INITARGS cpl)).

(CLASS-DIRECT-INITARGS class) => list of initarg names.  This works by
computing the applicable methods for ALLOCATE-INSTANCE and for
INITIALIZE-INSTANCE and examining their lambda-lists (using
METHOD-KEYWORD-NAMES), then combining that with the class's list of
slot-filling initargs.

(CLASS-ALL-INITARG-DEFAULTS class)
   => ((initarg-name default-value-function default-value-form)...)

(CLASS-DIRECT-INITARG-DEFAULTS class)
   => ((initarg-name default-value-function default-value-form)...)
This reflects the :DEFAULT-INITARGS option.  Default-value-form is the form
that was originally specified, and is retained purely for explanatory
purposes.  default-value-function is what gets actually called; its effect is
equivalent to enclosing default-value-form in the appropriate lexical
environment.  Default-value-function takes no arguments.

(CLASS-ALL-SLOT-INITARGS class) => ((initarg-name slot-name...)...)

(CLASS-DIRECT-SLOT-INITARGS class) => ((initarg-name slot-name...)...)
This reflects the :INITARG slot-option.

(COMPUTE-APPLICABLE-METHODS generic argument-list) => list of methods

(METHOD-KEYWORD-NAMES method) => list of symbols or &ALLOW-OTHER-KEYS,
indicating the keyword names of the keyword parameter specifiers in
the method's lambda-list.  The result is the symbol &ALLOW-OTHER-KEYS
instead of a list if the method's lambda-list contains that symbol.


>>> Meta-object functions

(ALLOCATE-INSTANCE class &key &allow-other-keys) => instance

Meta-users can replace the system-supplied, implementation-dependent method
for this.  Any keyword arguments accepted by applicable ALLOCATE-INSTANCE
methods become valid initargs.

(CHECK-INITARGS class initarg-list)

Meta-users could replace the system-supplied method that implements the
normal rules for initarg validity.

(DEFAULT-INITARGS class initarg-list) => initarg-list

The system-supplied method implements the :DEFAULT-INITARGS class option
by appending initargs that do not appear in initarg-list to the end
of the returned list.  The initarg-list supplied as an argument is not
modified.  The order of initargs appended to the list is determined by
the duplicate-initarg rules listed earlier.

(FINALIZE-INHERITANCE class &key slots methods initargs)

This is called by the system at least once before a class is instantiated, and
is called again whenever anything relevant changes.  System-supplied methods
for this conspire with methods for CHECK-INITARGS, etc., to make MAKE-INSTANCE
faster.  Users with their own optimization needs can add methods for this
generic function that will precompute things based on inherited information,
and update the precomputed information whenever anything changes.

The :slots, :methods, and :initargs arguments are booleans that are true
when the specified type of inheritance needs to be recomputed.